package kam.fire;

import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.WrapperListAdapter;

/**
 * The RoomsController handles all logic associated with the Room List Screen.
 * The Rooms List provides a Listview of all rooms the current user has access
 * to.
 * 
 * @author Derek Kam
 * 
 */
public class RoomsController extends Activity implements OnItemClickListener {
	int userIndex;
	User user = new User();
	DatabaseHelper db = DatabaseHelper.getHelper(this);
	KamfireInstance kamfireInstance;

	/**
	 * unpacks userIndex, campsite, and apiToken information from the user
	 * bundle and calls populateRoomList().
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Bundle userBundle = getIntent().getExtras();
		userIndex = (Integer) userBundle.getSerializable("USER_INDEX");
		String campsite = (String) userBundle.getSerializable("USER_CAMPSITE");
		String apiToken = (String) userBundle.getSerializable("USER_APITOKEN");
		super.onCreate(savedInstanceState);
		kamfireInstance = new KamfireInstance(campsite, apiToken);
		setContentView(R.layout.roomslist);
		user = db.getUserByIndex(userIndex);

		populateRoomList();

	}

	/**
	 * takes the list of rooms from campfire as a perameter and calls
	 * crossCheckRooms() to check them against the list of rooms from campfire.
	 * if they are different the list of rooms in the database are replaced with
	 * the list from campfire.
	 * 
	 * @param rooms
	 */
	private void addRoomsToTable(ArrayList<Room> rooms) {
		ArrayList<Room> dbRooms = db.getRoomList(userIndex);

		if (!crossCheckRooms(rooms, dbRooms))// cross check rooms against
												// campfire and //
		// db; false == !=
		{
			for (Room room : dbRooms) {
				db.deleteRoom(room);
			}
			db.addRoom(rooms); // adds the list of rooms to the local table if
								// different from campfire
		}
		//
		// for (Room room: diffRooms(rooms,dbRooms)){
		// db.deleteRoom(room);
		//
		// }

	}

	/**
	 * the crossCheckRooms(ArrayList<Room> rooms) checks the list of rooms from
	 * campfire against the rooms from the database if they are the same returns
	 * true else returns false
	 * 
	 * @param rooms
	 *            list of rooms from campfire
	 * @param dbRooms
	 *            list of rooms from database
	 * @return
	 */
	private boolean crossCheckRooms(ArrayList<Room> rooms, ArrayList<Room> dbRooms) {

		boolean value = true;
		Room cfRoom = null;
		if (dbRooms.size() == rooms.size()) {
			for (Room dbRoom : dbRooms) {
				int index = dbRooms.indexOf(dbRoom);
				if (index > -1) {
					cfRoom = rooms.get(index);

					if (dbRoom.equals(cfRoom)) {
						rooms.get(index).setIndex(dbRoom.getIndex());
					} else {
						value = false;
						break;
					}
				}
			}
		} else {
			value = false;
		}

		return value;
	}

	/**
	 * the populateRoomList() if there is internet connection determined by
	 * checkConnection(), starts a new thread by calling
	 * downloadData().execute().
	 */
	private void populateRoomList() {

		if (checkConnection()) {
			new DownloadData().execute();
		} else {
			noConnection();
		}
	}

	/**
	 * the checkConnection() method returns whether or not the device has an
	 * internet connection. true if connected false if not.
	 * 
	 * @return
	 */
	private boolean checkConnection() {
		ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
		if (networkInfo != null && networkInfo.isConnected()) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * the updateRoomsList(ArrayList<Room> rooms) method takes a list of new
	 * rooms and adds them to the listViw of displayed rooms.
	 * 
	 * @param rooms
	 *            rooms list of new rooms in relation to what is currently
	 *            displayed in the list view.
	 */
	@SuppressWarnings("unchecked")
	private void updateRoomsList(ArrayList<Room> rooms) {
		ListView roomsView = (ListView) findViewById(R.id.roomsListView);
		// get adapter may not return the requested adapter and instead returns
		// a wrappedListAdapter
		ListAdapter ad = roomsView.getAdapter();
		ArrayAdapter<Room> adapter;
		// checks if returned adapter is the one requested. if null create a new
		// one else check if wrapped unwrap it
		if (ad != null && ad.getClass().equals(ArrayAdapter.class)) {
			adapter = (ArrayAdapter<Room>) ad;
			adapter.clear();
		} else if (ad != null && ad.getClass().equals(WrapperListAdapter.class)) {
			WrapperListAdapter wad = (WrapperListAdapter) ad;
			adapter = (ArrayAdapter<Room>) wad.getWrappedAdapter();
			adapter.clear();
		} else {
			adapter = new ArrayAdapter<Room>(this, android.R.layout.simple_list_item_1);

			roomsView.setAdapter(adapter);
			roomsView.setOnItemClickListener(this);
		}

		for (int x = 0; x < rooms.size(); x++) {
			adapter.add(rooms.get(x)); // adapter.addAll is not implemented
										// until api 11
		}

	}

	/**
	 * action on item clicked
	 */
	@SuppressWarnings("rawtypes")
	public void onItemClick(AdapterView arg0, View v, int position, long arg3) {

		Room roomClicked = (Room) arg0.getAdapter().getItem(position);
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setClassName(this, RoomController.class.getName());
		Bundle roomsBundle = new Bundle();
		roomsBundle.putSerializable("ROOM_INDEX", roomClicked.getIndex());
		roomsBundle.putSerializable("USER_CAMPSITE", user.getCampsite());
		roomsBundle.putSerializable("USER_APITOKEN", user.getApiAuthToken());
		roomsBundle.putSerializable("USER_INDEX", userIndex);
		intent.putExtras(roomsBundle);
		this.startActivity(intent);

	}

	/**
	 * the noConnection() method displays a toast to notify the user that there
	 * is no internet connection.
	 * 
	 */
	private void noConnection() {
		Toast toast = Toast.makeText(this, "No Internet Service", Toast.LENGTH_SHORT);
		toast.show();
	}

	/**
	 * the errorConnection() method displays a toast to notify the user that
	 * there was an error retrieving data.
	 * 
	 */
	private void errorConnection() {
		Toast toast = Toast.makeText(this, "Error retrieving data", Toast.LENGTH_SHORT);
		toast.show();
	}

	/**
	 * the DownloadData class extends Asynch task to create a new thread. the
	 * class handles the downloading of the list of rooms and displays a loading
	 * screen.
	 */
	private class DownloadData extends AsyncTask<Void, Boolean, Boolean> {
		ProgressDialog dialog;

		protected void onPreExecute() {
			dialog = ProgressDialog.show(RoomsController.this, "", "Loading...");
		}

		protected Boolean doInBackground(Void... params) {
			return kamfireInstance.populateRooms();
		}

		// onPostExecute displays the results of the AsyncTask.
		protected void onPostExecute(Boolean b) {
			if (dialog.isShowing()) {
				dialog.dismiss();
			}

			ArrayList<Room> roomList;
			if (b) {
				roomList = kamfireInstance.getRooms();
				addRoomsToTable(roomList);
			} else {
				errorConnection();
				roomList = db.getRoomList(userIndex);
			}
			updateRoomsList(roomList);
		}

	}

	// ===========Button Overrides

	/**
	 * create options menu
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		//group, item id, order, name
		menu.add(0, 0, 0, "Settings");
		return true;
	}
	
	/**
	 * handle the options item click
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    // Handle item selection
	    switch (item.getItemId()) {
	        case 0:
	            gotToOptions();
	            return true;
	        default:
	            return super.onOptionsItemSelected(item);
	    }
	}

	
	private void gotToOptions() {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setClassName(this, OptionsController.class.getName());

		this.startActivity(intent);
		
	}

	/**
	 * provides a prompt when backing out into login screen
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if ((keyCode == KeyEvent.KEYCODE_BACK)) {
			new AlertDialog.Builder(this).setTitle("Logout").setMessage("Are you sure you want to logout?")
					.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							finish();
						}
					}).setNegativeButton("No", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							// do nothing
						}
					}).show();
		}
		return super.onKeyDown(keyCode, event);
	}
}
